//
//  PageCell.m
//  NVAReader
//
//  Created by DuyLK on 6/15/14.
//  Copyright (c) 2014 com.nva.nvareader. All rights reserved.
//

#import "PageCell.h"
#include "common.h"
#include "mupdf/pdf.h"
#import <iso646.h>
#import "NVAWord.h"

#define STRIKE_HEIGHT (0.375f)
#define UNDERLINE_HEIGHT (0.075f)
#define LINE_THICKNESS (0.07f)
#define INK_THICKNESS (2.0f)

typedef struct rect_list_s rect_list;

struct rect_list_s
{
	fz_rect rect;
	rect_list *next;
};

static void drop_list(rect_list *list)
{
	while (list)
	{
		rect_list *n = list->next;
		fz_free(ctx, list);
		list = n;
	}
}

static NSImage *newImageWithPixmap(fz_pixmap *pix, CGDataProviderRef cgdata,NSSize sizeImage)
{
	int w = fz_pixmap_width(ctx, pix);
	int h = fz_pixmap_height(ctx, pix);
	CGColorSpaceRef cgcolor = CGColorSpaceCreateDeviceRGB();
	CGImageRef cgimage = CGImageCreate(w, h, 8, 32, 4 * w, cgcolor, kCGBitmapByteOrderDefault, cgdata, NULL, NO, kCGRenderingIntentDefault);
	NSImage *image = [[NSImage alloc] initWithCGImage:cgimage size:sizeImage];
    CGColorSpaceRelease(cgcolor);
	CGImageRelease(cgimage);
	return image;
}

static fz_display_list *create_page_list(fz_document *doc, fz_page *page)
{
	fz_display_list *list = NULL;
	fz_device *dev = NULL;
    
	fz_var(dev);
	fz_try(ctx)
	{
		list = fz_new_display_list(ctx);
		dev = fz_new_list_device(ctx, list);
		fz_run_page_contents(doc, page, dev, &fz_identity, NULL);
	}
	fz_always(ctx)
	{
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
		return NULL;
	}
    
	return list;
}

static fz_display_list *create_annot_list(fz_document *doc, fz_page *page)
{
	fz_display_list *list = NULL;
	fz_device *dev = NULL;
    
	fz_var(dev);
	fz_try(ctx)
	{
		fz_annot *annot;
		pdf_document *idoc = pdf_specifics(doc);
        
		if (idoc)
			pdf_update_page(idoc, (pdf_page *)page);
		list = fz_new_display_list(ctx);
		dev = fz_new_list_device(ctx, list);
		for (annot = fz_first_annot(doc, page); annot; annot = fz_next_annot(doc, annot))
			fz_run_annot(doc, page, annot, dev, &fz_identity, NULL);
	}
	fz_always(ctx)
	{
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
		return NULL;
	}
    
	return list;
}


static fz_pixmap *renderPixmap(fz_document *doc, fz_display_list *page_list, fz_display_list *annot_list, CGSize pageSize, CGSize screenSize, CGRect tileRect, float zoom)
{
	fz_irect bbox;
	fz_rect rect;
	fz_matrix ctm;
	fz_device *dev = NULL;
	fz_pixmap *pix = NULL;
	CGSize scale;
    
	screenSize.width *= screenScale;
	screenSize.height *= screenScale;
	tileRect.origin.x *= screenScale;
	tileRect.origin.y *= screenScale;
	tileRect.size.width *= screenScale;
	tileRect.size.height *= screenScale;
    
	scale = fitPageToScreen(pageSize, screenSize);
	fz_scale(&ctm, scale.width * zoom, scale.height * zoom);
    
	bbox.x0 = tileRect.origin.x;
	bbox.y0 = tileRect.origin.y;
	bbox.x1 = tileRect.origin.x + tileRect.size.width;
	bbox.y1 = tileRect.origin.y + tileRect.size.height;
	fz_rect_from_irect(&rect, &bbox);
    
	fz_var(dev);
	fz_var(pix);
	fz_try(ctx)
	{
		pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
		fz_clear_pixmap_with_value(ctx, pix, 255);
        
		dev = fz_new_draw_device(ctx, pix);
		fz_run_display_list(page_list, dev, &ctm, &rect, NULL);
		fz_run_display_list(annot_list, dev, &ctm, &rect, NULL);
	}
	fz_always(ctx)
	{
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, pix);
		return NULL;
	}
    
	return pix;
}

#pragma start copy
static NSArray *enumerateWords(fz_document *doc, fz_page *page)
{
	fz_text_sheet *sheet = NULL;
	fz_text_page *text = NULL;
	fz_device *dev = NULL;
	NSMutableArray *lns = [NSMutableArray array];
	NSMutableArray *wds;
	NVAWord *word;
    
	if (!lns)
		return NULL;
    
	fz_var(sheet);
	fz_var(text);
	fz_var(dev);
    
	fz_try(ctx);
	{
		int b, l, c;
        
		sheet = fz_new_text_sheet(ctx);
		text = fz_new_text_page(ctx);
		dev = fz_new_text_device(ctx, sheet, text);
		fz_run_page(doc, page, dev, &fz_identity, NULL);
		fz_free_device(dev);
		dev = NULL;
        
		for (b = 0; b < text->len; b++)
		{
			fz_text_block *block;
            
			if (text->blocks[b].type != FZ_PAGE_BLOCK_TEXT)
				continue;
            
			block = text->blocks[b].u.text;
            
			for (l = 0; l < block->len; l++)
			{
				fz_text_line *line = &block->lines[l];
				fz_text_span *span;
                
				wds = [NSMutableArray array];
				if (!wds)
					fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to create word array");
                
				word = [NVAWord word];
				if (!word)
					fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to create word");
                
				for (span = line->first_span; span; span = span->next)
				{
					for (c = 0; c < span->len; c++)
					{
						fz_text_char *ch = &span->text[c];
						fz_rect bbox;
						CGRect rect;
                        
						fz_text_char_bbox(&bbox, span, c);
						rect = CGRectMake(bbox.x0, bbox.y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0);
                        
						if (ch->c != ' ')
						{
							[word appendChar:ch->c withRect:rect];
						}
						else if (word.string.length > 0)
						{
							[wds addObject:word];
							word = [NVAWord word];
							if (!word)
								fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to create word");
						}
					}
				}
                
				if (word.string.length > 0)
					[wds addObject:word];
                
				if ([wds count] > 0)
					[lns addObject:wds];
			}
		}
	}
	fz_always(ctx);
	{
		fz_free_text_page(ctx, text);
		fz_free_text_sheet(ctx, sheet);
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
		lns = NULL;
	}
    
	return [lns retain];
}

static void addMarkupAnnot(fz_document *doc, fz_page *page, int type, NSArray *rects,float red,float green, float blue)
{
	pdf_document *idoc;
	fz_point *quadpts = NULL;
	float color[3];
	float alpha;
	float line_height;
	float line_thickness;
    
	idoc = pdf_specifics(doc);
	if (!idoc)
		return;
    
	switch (type)
	{
		case FZ_ANNOT_HIGHLIGHT:
			color[0] = red;
			color[1] = green;
			color[2] = blue;
			alpha = 0.5;
			line_thickness = 1.0;
			line_height = 0.5;
			break;
		case FZ_ANNOT_UNDERLINE:
			color[0] = red;
			color[1] = green;
			color[2] = blue;
			alpha = 1.0;
			line_thickness = LINE_THICKNESS;
			line_height = UNDERLINE_HEIGHT;
			break;
		case FZ_ANNOT_STRIKEOUT:
			color[0] = red;
			color[1] = green;
			color[2] = blue;
			alpha = 1.0;
			line_thickness = LINE_THICKNESS;
			line_height = STRIKE_HEIGHT;
			break;
	}
    
	fz_var(quadpts);
	fz_try(ctx)
	{
		int i;
		pdf_annot *annot;
        
		quadpts = fz_malloc_array(ctx, (int)(rects.count * 4), sizeof(fz_point));
		for (i = 0; i < rects.count; i++)
		{
			NSRect rect = [[rects objectAtIndex:i] rectValue];
			float top = rect.origin.y;
			float bot = top + rect.size.height;
			float left = rect.origin.x;
			float right = left + rect.size.width;
			quadpts[i*4].x = left;
			quadpts[i*4].y = bot;
			quadpts[i*4+1].x = right;
			quadpts[i*4+1].y = bot;
			quadpts[i*4+2].x = right;
			quadpts[i*4+2].y = top;
			quadpts[i*4+3].x = left;
			quadpts[i*4+3].y = top;
		}
        
		annot = pdf_create_annot(idoc, (pdf_page *)page, type);
		pdf_set_markup_annot_quadpoints(idoc, annot, quadpts, (int)(rects.count*4));
		pdf_set_markup_appearance(idoc, annot, color, alpha, line_thickness, line_height);
	}
	fz_always(ctx)
	{
		fz_free(ctx, quadpts);
	}
	fz_catch(ctx)
	{
		printf("Annotation creation failed\n");
	}
}


static rect_list *updatePage(fz_document *doc, fz_page *page)
{
	rect_list *list = NULL;
    
	fz_var(list);
	fz_try(ctx)
	{
		pdf_document *idoc = pdf_specifics(doc);
        
		if (idoc)
		{
			fz_annot *annot;
            
			pdf_update_page(idoc, (pdf_page *)page);
			while ((annot = (fz_annot *)pdf_poll_changed_annot(idoc, (pdf_page *)page)) != NULL)
			{
				rect_list *node = fz_malloc_struct(ctx, rect_list);
                
				fz_bound_annot(doc, annot, &node->rect);
				node->next = list;
				list = node;
			}
		}
	}
	fz_catch(ctx)
	{
		drop_list(list);
		list = NULL;
	}
    
	return list;
}

static void updatePixmap(fz_document *doc, fz_display_list *page_list, fz_display_list *annot_list, fz_pixmap *pixmap, rect_list *rlist, CGSize pageSize, CGSize screenSize, CGRect tileRect, float zoom)
{
	fz_irect bbox;
	fz_rect rect;
	fz_matrix ctm;
	fz_device *dev = NULL;
	CGSize scale;
    
	screenSize.width *= screenScale;
	screenSize.height *= screenScale;
	tileRect.origin.x *= screenScale;
	tileRect.origin.y *= screenScale;
	tileRect.size.width *= screenScale;
	tileRect.size.height *= screenScale;
    
	scale = fitPageToScreen(pageSize, screenSize);
	fz_scale(&ctm, scale.width * zoom, scale.height * zoom);
    
	bbox.x0 = tileRect.origin.x;
	bbox.y0 = tileRect.origin.y;
	bbox.x1 = tileRect.origin.x + tileRect.size.width;
	bbox.y1 = tileRect.origin.y + tileRect.size.height;
	fz_rect_from_irect(&rect, &bbox);
    
	fz_var(dev);
	fz_try(ctx)
	{
		while (rlist)
		{
			fz_irect abox;
			fz_rect arect = rlist->rect;
			fz_transform_rect(&arect, &ctm);
			fz_intersect_rect(&arect, &rect);
			fz_round_rect(&abox, &arect);
			if (!fz_is_empty_irect(&abox))
			{
				fz_clear_pixmap_rect_with_value(ctx, pixmap, 255, &abox);
				dev = fz_new_draw_device_with_bbox(ctx, pixmap, &abox);
				fz_run_display_list(page_list, dev, &ctm, &arect, NULL);
				fz_run_display_list(annot_list, dev, &ctm, &arect, NULL);
				fz_free_device(dev);
				dev = NULL;
			}
			rlist = rlist->next;
		}
	}
	fz_always(ctx)
	{
		fz_free_device(dev);
	}
	fz_catch(ctx)
	{
	}
}

static void addInkAnnot(fz_document *doc, fz_page *page, NSArray *curves,float red, float green,float blue)
{
	pdf_document *idoc;
	fz_point *pts = NULL;
	int *counts = NULL;
	int total;
	float color[3] = {red,green,blue};
    
	idoc = pdf_specifics(doc);
	if (!idoc)
		return;
    
	fz_var(pts);
	fz_var(counts);
	fz_try(ctx)
	{
		int i, j, k, n;
		pdf_annot *annot;
        
		n = (int)curves.count;
        
		counts = fz_malloc_array(ctx, n, sizeof(int));
		total = 0;
        
		for (i = 0; i < n; i++)
		{
			NSArray *curve = [curves objectAtIndex:i];
			counts[i] = (int)curve.count;
			total += curve.count;
		}
        
		pts = fz_malloc_array(ctx, total, sizeof(fz_point));
        
		k = 0;
		for (i = 0; i < n; i++)
		{
			NSArray *curve = [curves objectAtIndex:i];
			int count = counts[i];
            
			for (j = 0; j < count; j++)
			{
				NSPoint pt = [[curve objectAtIndex:j] pointValue];
				pts[k].x = pt.x;
				pts[k].y = pt.y;
				k++;
			}
		}
        
		annot = pdf_create_annot(idoc, (pdf_page *)page, FZ_ANNOT_INK);
		pdf_set_ink_annot_list(idoc, annot, pts, counts, n, color, INK_THICKNESS);
	}
	fz_always(ctx)
	{
		fz_free(ctx, pts);
		fz_free(ctx, counts);
	}
	fz_catch(ctx)
	{
		printf("Annotation creation failed\n");
	}
}


static NSArray *enumerateAnnotations(fz_document *doc, fz_page *page)
{
	fz_annot *annot;
	NSMutableArray *arr = [NSMutableArray arrayWithCapacity:10];
    
	for (annot = fz_first_annot(doc, page); annot; annot = fz_next_annot(doc, annot))
		[arr addObject:[NVAAnnotation annotFromAnnot:annot forDoc:doc]];
    
	return [arr retain];
}

#pragma end copy

#pragma endimagepdf
@implementation PageCell
@synthesize title = _title;
@synthesize image = _image;
@synthesize selectText = _selectText;
#pragma imagepdf
+ (void)updateCount:(BOOL)status {
	static NSInteger count = 0;
	if (status) {
		count++;
	} else {
		count--;
	}
}

-(void) addTextSelectView:(BOOL)add
{
    if(add)
    {
        _isSelect = YES;
        _isDraw = NO;
        if(!_selectText)
        {
            [self addSelectText];
        }else
        {
            [_selectText setIsDrawTool:_isDraw];
        }
        [self setNeedsDisplay:YES];
        NSLog(@"Is Select");
    }else{
        _isSelect= NO;
        _isDraw = NO;
        if (_selectText)
        {
            [_selectText removeFromSuperview];
            [_selectText release];
            _selectText = nil;
        }
    }
}

-(void)setIsDrawTool:(BOOL)isDraw
{
    _isSelect = NO;
    _isDraw = isDraw;
    if (!_selectText) {
        [self addSelectText];
        [self setNeedsDisplay:YES];
    }else
    {
        [_selectText setIsDrawTool:isDraw];
    }
}

-(void) changeWidthHeight:(int)widthPage height:(int)heightPage;
{
    _widthPage = widthPage;
    _heightPage = heightPage;
     CGSize sizePage =  CGSizeMake(_widthPage,_heightPage);
    if (_selectText){
        [_selectText setPageSize:sizePage witdth:_widthPage height:_heightPage];
    }
}

- (id)	initWithReusableIdentifier: (NSString*)identifier
{
	if(( self = [super initWithReusableIdentifier: identifier] ))
	{
		[PageCell updateCount:YES];
	}
	return self;
}

- (void) dealloc
{
	[PageCell updateCount:NO];
    [_selectText release];
    _selectText = nil;
	[_title release];
	_title = nil;
    [_image release];
    [_hitView release];
    _hitView = nil;
    _image = nil;
	[super dealloc];
}

- (void) prepareForReuse
{
    [_selectText removeFromSuperview];
    [_selectText release];
    _selectText = nil;
	[_title release];
	_title = nil;
    [_image release];
    [_hitView release];
    _hitView = nil;
    _image = nil;
}

- (void)drawRect:(NSRect)dirtyRect
{
    [NSGraphicsContext saveGraphicsState];
	NSRect bounds = [self bounds];
    //text
    [[NSColor blackColor] set];
    //draw page
    int numberPage = [_title intValue] - 1;
    if(![self isZoom])
    {
        NSRect rectTemp = NSMakeRect(0, 0, _widthPage -10, _heightPage -10);
        fz_try(ctx)
        {
            fz_rect bound_page;
            page = fz_load_page(_doc, numberPage);
            fz_bound_page(_doc, page, &bound_page);
            pageSize.width = bound_page.x1 - bound_page.x0;
            pageSize.height = bound_page.y1 - bound_page.y0;
            
            NSRect rectPos = NSMakeRect(0 + bounds.size.width/2 - (_widthPage-10)/2 ,5, rectTemp.size.width , rectTemp.size.height);
            if(!_image)
            {
                if (!page)
                    return;
                page_list = create_page_list(_doc, page);
                annot_list = create_annot_list(_doc, page);
                CGSize imageViewSize =  CGSizeMake(_widthPage -10, (_heightPage - 10));
                CGRect rect = (CGRect){{0.0, 0.0},{_widthPage -10, (_heightPage -10) }};
                image_pix = renderPixmap(_doc, page_list, annot_list, pageSize , imageViewSize , rect, 1.0);
                CGDataProviderRelease(imageData);
                imageData = wrapPixmap(image_pix);
                [_image release];
                _image = nil;
                _image = newImageWithPixmap(image_pix, imageData,rect.size);
                [_delegate scrollPage:numberPage];
            }
            //draw boundpage
            NSColor *colorBound = [NSColor colorWithCalibratedRed:0.7 green:0.7 blue:0.7 alpha:0.7];
            [colorBound set];
            NSBezierPath* roundedRect = [NSBezierPath bezierPathWithRoundedRect:rectPos xRadius:3 yRadius:3];
            [roundedRect setLineWidth:2];
            [roundedRect stroke];
            //draw shadow
            NSShadow* theShadow = [[NSShadow alloc] init];
            [theShadow setShadowOffset:NSMakeSize(2.0, -3.0)];
            [theShadow setShadowBlurRadius:2.0];
            // Use a partially transparent color for shapes that overlap.
            [theShadow setShadowColor:[[NSColor blackColor]
                                       colorWithAlphaComponent:0.4]];
            [theShadow set];
            
            if (_image) {
                [_image drawInRect:rectPos fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
                [_selectText setFrame:rectPos];
            }
            if (_searchData) {
                if (!_hitView && [_searchData objectForKey:[NSNumber numberWithInt:(numberPage+1)]]) {
                    _hitView =[_searchData objectForKey:[NSNumber numberWithInt:(numberPage+1)]];
                }
            }else
            {
                _hitView = nil;
            }
            if (_hitView) {
                for (int i =0; i < [_hitView hitCount]; i++) {
                    CGRect rect = [_hitView getHitSearch][i];
                    float scale = rectPos.size.width/pageSize.width;
                    NSColor *color = [NSColor colorWithRed: 0x25/255.0 green: 0x72/255.0 blue: 0xAC/255.0 alpha: 0.5];
                    [color set];
                    NSRect rectSearch = NSMakeRect(rectPos.origin.x + rect.origin.x * scale,rectPos.size.height - rect.origin.y * scale
                                                   - rect.size.height * scale,rect.size.width * scale ,rect.size.height * scale + 5);
                    NSBezierPath* rounded = [NSBezierPath bezierPathWithRect:rectSearch];
                    [rounded fill];
                }
            }
            
            [self addSelectText];
        }
        fz_catch(ctx)
        {
            return;
        }
    
    }else
    {
        NSRect bounds = [self bounds];
        NSRect rectTemp = NSMakeRect(0, 0, bounds.size.width - 10, bounds.size.height -10);
        fz_try(ctx)
        {
            fz_rect bound_page;
            page = fz_load_page(_doc, numberPage);
            fz_bound_page(_doc, page, &bound_page);
            pageSize.width = bound_page.x1 - bound_page.x0;
            pageSize.height = bound_page.y1 - bound_page.y0;
            
            if (!page)
                return;
            page_list = create_page_list(_doc, page);
            annot_list = create_annot_list(_doc, page);
            
            NSRect rectPos = NSMakeRect(5,5, rectTemp.size.width , rectTemp.size.height);
            
            if(!_image)
            {
                CGSize imageViewSize =  CGSizeMake(rectTemp.size.width,rectTemp.size.height);
                CGRect rect = (CGRect){{0.0, 0.0},{_widthPage -10, (_heightPage -10) }};
                image_pix = renderPixmap(_doc, page_list, annot_list, pageSize, imageViewSize , rect, 1.0);
                CGDataProviderRelease(imageData);
                imageData = wrapPixmap(image_pix);
                [_image release];
                _image = nil;
                _image = newImageWithPixmap(image_pix, imageData,rect.size);
                [_delegate scrollPage:numberPage];
            }
            
            //draw boundpage
            NSColor *colorBound = [NSColor colorWithCalibratedRed:0.7 green:0.7 blue:0.7 alpha:0.8];
            [colorBound set];
            NSBezierPath* roundedRect = [NSBezierPath bezierPathWithRoundedRect:rectPos xRadius:3 yRadius:3];
            [roundedRect setLineWidth:2];
            [roundedRect stroke];
            //draw shadow
            NSShadow* theShadow = [[NSShadow alloc] init];
            [theShadow setShadowOffset:NSMakeSize(2.0, -3.0)];
            [theShadow setShadowBlurRadius:2.0];
            // Use a partially transparent color for shapes that overlap.
            [theShadow setShadowColor:[[NSColor blackColor]
                                       colorWithAlphaComponent:0.4]];
            [theShadow set];
            //draw image
            if (_image) {
                [_image drawInRect:rectPos fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
                [_selectText setFrame:rectPos];
            }
            if (_searchData) {
                if (!_hitView && [_searchData objectForKey:[NSNumber numberWithInt:(numberPage + 1)]]) {
                    _hitView =[_searchData objectForKey:[NSNumber numberWithInt:(numberPage + 1 )]];
                }
            }else
            {
                _hitView = nil;
            }
            if (_hitView) {
                for (int i =0; i < [_hitView hitCount]; i++) {
                    CGRect rect = [_hitView getHitSearch][i];
                    CGSize scale = fitPageToScreen(pageSize, CGSizeMake(rectPos.size.width , rectPos.size.height));
                    NSColor *color = [NSColor colorWithRed: 0x25/255.0 green: 0x72/255.0 blue: 0xAC/255.0 alpha: 0.5];
                    [color set];
                    NSRect rectSearch = NSMakeRect(5 + rect.origin.x * scale.width,rectPos.size.height - rect.origin.y * scale.height
                                                   - rect.size.height * scale.height,rect.size.width * scale.width ,rect.size.height * scale.height);
                    NSBezierPath* rounded = [NSBezierPath bezierPathWithRect:rectSearch];
                    [rounded fill];
                }
            }
            [self addSelectText];
        }fz_catch(ctx)
        {
            return;
        }
    }
	[super drawRect: dirtyRect];
    [NSGraphicsContext restoreGraphicsState];
}

-(void) update
{
    if(_doc && page)
    {
        rect_list *rlist = updatePage(_doc, page);
        fz_drop_display_list(ctx, annot_list);
        annot_list = create_annot_list(_doc, page);
         CGRect rect = (CGRect){{0.0, 0.0},{_widthPage -10, (_heightPage -10) }};
        CGSize imageViewSize =  CGSizeMake(_widthPage -10,_heightPage);
        updatePixmap(_doc, page_list, annot_list, image_pix, rlist,  pageSize, imageViewSize , rect, 1.0);
        drop_list(rlist);
        NSImage *image = newImageWithPixmap(image_pix, imageData,rect.size);
        [_image release];
        _image = nil;
        _image = image;
    }
}

-(void) addSelectText{
    if(!_selectText && _isSelect)
    {
        if (_doc && page) {
            NSArray *words = enumerateWords(_doc, page);
            _selectText = [[SelectTextView alloc] initWithWords:words pageSize:pageSize witdth:_widthPage height:_heightPage];
            _selectText.delegate = self;
            [words release];
            [self addSubview:_selectText];
        }
    }
    if(!_selectText && _isDraw)
    {
        if (_doc && page) {
            NSArray *words = enumerateWords(_doc, page);
            _selectText = [[SelectTextView alloc] initWithWords:words pageSize:pageSize witdth:_widthPage height:_heightPage];
            [_selectText setIsDrawTool:_isDraw];
            _selectText.delegate = self;
            [words release];
            [self addSubview:_selectText];
        }
    }
}

-(void) rightMouseDown:(NSEvent *)theEvent
{
    if(_selectText && _isSelect)
    {
        NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@"Contextual Menu"];
        [theMenu insertItemWithTitle:@"Copy text                    " action:@selector(copy:) keyEquivalent:@"" atIndex:0];
        [theMenu insertItem:[NSMenuItem separatorItem] atIndex:1];
        [theMenu insertItemWithTitle:@"Highlight text" action:@selector(highlight:) keyEquivalent:@"" atIndex:2];
        [theMenu insertItemWithTitle:@"Underline text" action:@selector(underline:) keyEquivalent:@"" atIndex:3];
        [theMenu insertItemWithTitle:@"Strikeout text" action:@selector(strike:) keyEquivalent:@"" atIndex:4];
        [theMenu setMinimumWidth:400];
        [NSMenu popUpContextMenu:theMenu withEvent:theEvent forView:self];
    }
}

-(IBAction)copy:(id)sender
{
    if (_selectText && _isSelect) {
        NSArray *rects = [_selectText selectionRects];
        if (rects.count == 0)
        {
            NSRunAlertPanel(@"Sorry!", @"Please select text to copy text", @"OK", @"Cancel", nil);
            return;
        }
        NSString *text = [_selectText selectedText];
        [rects retain];
        NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
        [pasteboard clearContents];
        [pasteboard setString:text forType:NSStringPboardType];
    }
    [self textSelectModeOff];
}

-(IBAction)highlight:(id)sender
{
    if (_selectText && _isSelect) {
        [self saveSelectionAsMarkup:FZ_ANNOT_HIGHLIGHT];
    }
}

-(IBAction)underline:(id)sender
{
    if (_selectText && _isSelect) {
        [self saveSelectionAsMarkup:FZ_ANNOT_UNDERLINE];
    }
}

-(IBAction)strike:(id)sender
{
    if (_selectText && _isSelect) {
        [self saveSelectionAsMarkup:FZ_ANNOT_STRIKEOUT];
    }
}
- (void) textSelectModeOff
{
    if (_selectText)
    {
        [_selectText removeFromSuperview];
        [_selectText release];
        _selectText = nil;
    }
}
-(void) saveSelectionAsMarkup:(int)type
{
    NSArray *rects = [_selectText selectionRects];
	if (rects.count == 0)
    {
        if(type == FZ_ANNOT_HIGHLIGHT)
        {
            NSRunAlertPanel(@"Sorry!", @"Please select text to highlight text", @"OK", @"Cancel", nil);
        }
        if(type == FZ_ANNOT_UNDERLINE)
        {
            NSRunAlertPanel(@"Sorry!", @"Please select text to underline text", @"OK", @"Cancel", nil);
        }
        if(type == FZ_ANNOT_STRIKEOUT)
        {
            NSRunAlertPanel(@"Sorry!", @"Please select text to strike text", @"OK", @"Cancel", nil);
        }
		return;
    }
	[rects retain];
    CGFloat red, green, blue;
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    if(type == FZ_ANNOT_HIGHLIGHT)
    {
        if([ud boolForKey:@"ColorHighLight"])
        {
            int colorHightLignt = (int) [[NSUserDefaults standardUserDefaults] integerForKey:@"ColorHighLight"];
            NSColor *colorhight = colorDecode(colorHightLignt);
            [colorhight getRed:&red green:&green blue:&blue alpha:nil];
        }
        else
        {
            red = 1.0,green = 1.0;blue = 0.0;
        }
    }
    else if(type == FZ_ANNOT_UNDERLINE)
    {
        if([ud boolForKey:@"ColorUnderLine"])
        {
            int colorHightLignt = (int) [[NSUserDefaults standardUserDefaults] integerForKey:@"ColorUnderLine"];
            NSColor *colorhight = colorDecode(colorHightLignt);
            [colorhight getRed:&red green:&green blue:&blue alpha:nil];
        }
        else
        {
             red = 0.0; green = 0.0 ;blue = 1.0;
        }
    }
    else if(type == FZ_ANNOT_STRIKEOUT)
    {
        if([ud boolForKey:@"ColorStrikeOut"])
        {
            int colorHightLignt = (int) [[NSUserDefaults standardUserDefaults] integerForKey:@"ColorStrikeOut"];
            NSColor *colorhight = colorDecode(colorHightLignt);
            [colorhight getRed:&red green:&green blue:&blue alpha:nil];
        }
        else
        {
            red = 1.0; green = 0.0 ;blue = 1.0;
        }
    }
    
    addMarkupAnnot(_doc, page, type, rects,red,green,blue);
    [rects release];
    [self update];
    [self loadAnnotations];
	[self textSelectModeOff];
}

-(void) loadAnnotations
{
    if (_doc && page) {
        NSArray *annots = enumerateAnnotations(_doc, page);
        [annotations release];
		annotations = annots;
    }
}

-(void)evenEndDraw
{
    if(_selectText && _isDraw)
    {
        NSArray *curves = _selectText.curves;
        if (curves.count == 0)
            return;
        
        [curves retain];
        CGFloat red, green, blue;
        NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
        if([ud boolForKey:@"ColorDraw"])
        {
            int colorHightLignt = (int) [[NSUserDefaults standardUserDefaults] integerForKey:@"ColorDraw"];
            NSColor *colorhight =colorDecode(colorHightLignt);
            [colorhight getRed:&red green:&green blue:&blue alpha:nil];
        }
        else
        {
            red = 1.0; green = 0.0 ;blue = 0.0;
        }
        addInkAnnot(_doc, page, curves,red,green,blue);
		[curves release];
        curves = nil;
        [self update];
        [self loadAnnotations];
        [self textSelectModeOff];
    }
}
@end
